#pragma once

#include <string.h>

#include <QtGlobal>
#include <list>
#include <map>
#include <mutex>
#include <string>

#include "bondlib.h"

struct MarketStreamType2Body {  // MS_TYPE = 2,成交状态
  time_t m_createTime;          // 创建时间
  // char		m_bondCode[12];				//债券代码
  char m_bondkey[32 + 1];   // key
  char m_listedmarket[12];  // 市场代码
  // char		m_bondShortName[32];		//简称
  char m_price[12];       // 收益率
  char m_volume[64];      // 有可能出现"40234+3212"的情况、
  char m_fullPrice[12];   //
  char m_cleanPrice[12];  //
  char m_yield[12];       // 收益率
  char m_rebate[4];       // 是否返点(0-不返，1返点)
  char m_return_point
      [12];  // 返点值(例:
             // F0.10),值可以是0.0,也可以是空，代表不同的含义,空代表"全返",要注意区分
  char m_id[32 + 1];     // 唯一编号
  char m_dealStatus[2];  //"0 ~ 3: 客户端显示成交，		4 ~ 6:
                         //客户端删除成交"    8:撤销成交
  char m_quotetype[4];  // 报价类型，0-有意向；1-净价；2-全价；3-收益率；4-利差
  /*status "0: 初始化
  1: 单方确认
  2: 待审核,双方交易员确认
  3: 已完成
  4: 已作废
  5: 已撤销
  6: 删除"
  */
  char m_exercise[2];  // 行权到期  (0-行权 1-到期)
  bool IsCleanPrice() const { return strcmp(m_quotetype, "1") == 0; }  // 净价
  bool IsFullPrice() const { return strcmp(m_quotetype, "2") == 0; }   // 全价
};

typedef struct MarketStreamInfo {  // 参见xQBMarketStreamUnit_c
  char m_company_id[4];            // 经纪公司ID
  // char		m_company_name[64];			//经纪公司名称
  char m_dept[32];  // 业务类型，如：Bond IRS',
  char m_type
      [5];  // 消息类型\n1：最优报价\n2：成交状态\n3：我的报价进入区间\n4：我的报价\n5：我的成交单',
  char m_operate[5];  // 消息子类
  char m_status[5];   // 2--无效
  // char		m_quotetype[4];
  // //报价类型，0-有意向；1-净价；2-全价；3-收益率；4-利差
  time_t m_modify_time;          // datetime,
  time_t m_create_time;          // datetime,
  int m_indexID;                 // 报价序号，日内自增
  MarketStreamType2Body m_body;  // 市场成交
  const bool operator<(const MarketStreamInfo& obj) const {
    // compare by time,if time equals,compare by indexid
    time_t t1 = qMax(m_create_time, m_modify_time);
    time_t t2 = qMax(obj.m_create_time, obj.m_modify_time);
    return t1 == t2 ? (m_indexID > obj.m_indexID) : (t1 > t2);
    // return (max(m_create_time,m_modify_time) >
    // max(obj.m_create_time,obj.m_modify_time));
  }
  const bool operator==(const MarketStreamInfo& obj) const {
    if (strcmp(m_body.m_bondkey, obj.m_body.m_bondkey) == 0 &&
        strcmp(m_body.m_listedmarket, obj.m_body.m_listedmarket) == 0 &&
        strcmp(m_company_id, obj.m_company_id) == 0)
      return true;
    return false;
  }
  MarketStreamInfo() { memset(this, 0, sizeof(MarketStreamInfo)); }
  bool IsDealStatusCanceled() const { return atoi(m_body.m_dealStatus) == 8; }
} MarketInfo;

struct MarketStreamRec {
  // char		m_bondCode[12];				//债券代码
  char m_bondkey[32 + 1];   // key
  char m_listedmarket[12];  // 市场代码
  float m_avePrice;         // 平均成交
  float m_aveclPrice;       // 成交净价
  int m_nTransCount;        // 成交笔数
  int m_nRealCount;         // 真实成交
  int m_nClanCount;         // 净价成交
  char m_Maxprice[12];      // 最高价
  char m_Minprice[12];      // 最低价

  bool m_bHistory;      // 是否为历史
  float m_YesAdvPrice;  // 昨日平均
  double m_dbAmount;    // 债券余额

  char m_issuerRating[6];      // 主体评级
  char m_issuerBondRating[6];  // 债项评级

  MarketStreamRec() {
    memset(this, 0, sizeof(MarketStreamRec));
    m_dbAmount = 0.0;
    m_YesAdvPrice = 0.0f;
  }
};

class S_BONDLIB_EXPORT CMarketInfoMap {
 public:
  std::map<int, int> m_map;
  int m_nTotal = 0;

 public:
  CMarketInfoMap() = default;
  bool Clear() {
    m_map.clear();
    m_nTotal = 0;
    return true;
  }
  void SetSize(int nNum) { m_nTotal = nNum; }
};

class S_BONDLIB_EXPORT CMarketToprec {
 public:
  std::map<int, MarketStreamRec> m_map;
  int m_nTotal = 0;

 public:
  CMarketToprec() = default;
  void SetSize(int nNum) { m_nTotal = nNum; }
};

class S_BONDLIB_EXPORT CMarketStreamlst {
 public:
  std::list<MarketStreamInfo> m_list;
  std::map<std::string /*comb key*/, MarketStreamRec> m_Record;
};

class S_BONDLIB_EXPORT CMarketStreamBase {
 public:
  enum kStreamType { kStreamTypeBond, kStreamTypeExchange, kStreamTypeCFets };
  enum kStatType {
    kStatTypeMin,
    kStatTypeByType,
    kStatTypeByDate,
    kStatTypeTransDate,
    kStatTypeRatioType,
    kStatTypeTransRating,
    kStatTypeTransNFRate,
    kStatTypeMax
  };
  enum emMktStreamPage {
    mktPage_Interest = 0,    // 利率债
    mktPage_Credit,          // 信用债
    mktPage_TFRelative,      // 国债期货相关券
    mktPage_NCD,             // NCD
    mktPage_Credit_Inc_NCD,  // 信用债含NCD
  };
  enum MarktType {
    MarktCountry = 0x00,
    MarktCenter = 0x01,
    MarktFinance = 0x02,
    MarktLocal = 0x03,
    MarktShort = 0x04,
    MarktChina = 0x05,
    MarktEnterpr = 0x06,
    MarktOther = 0x07,
    MarktNFRate = 0x08,
    MarktMunicp = 0x09,
    MarktAll = 0x0A
  };
  enum MarktRating {
    RatingNone = 0x00,
    RatingAll = 0x01,
    RatingAAA = 0x02,
    RatingAAP = 0x03,
    RatingAA = 0x04,
    RatingAAN = 0x05,
    RatingAP = 0x06,
    RatingA = 0x07,
    RatingOther = 0x08,
  };
  enum MarktDate {
    DateRange1 = 0x00,
    DateRange2 = 0x01,
    DateRange3 = 0x02,
    DateRange4 = 0x03,
    DateRange5 = 0x04,
    DateRange6 = 0x05,
    DateRange7 = 0x06,
    DateRange8 = 0x07,
    DateRange9 = 0x08
  };
  enum MarktIssuer {
    IssuerNone = 0x00,
    IssuerGUOK = 0x01,
    IssuerIEPT = 0x02,
    IssuerFADE = 0x03,
  };
  enum MarktRateTyp {
    RatypeNone = 0x00,
    RatypeShibor = 0x01,
    RatypeDepo = 0x02,
    RatypeFixed = 0x03,
  };
  enum CFETSDealType {
    CFETS_DEALTYPE_QUOTE = 0,
    CFETS_DEALTYPE_TICK = 1,
    CFETS_DEALTYPE_MARKETMAKER = 2,
  };
  static int GetBondDealInvalidateDay();
  // static bool		IsValidTypeMarketStream(const char * szBondKey,
  // const char * szMkt, MarktType mkType, bool bCredit = false, bool bNeedFixed
  // = false);
  static bool GetTodayMarketRecord(CMarketToprec& MarketInfo,
                                   const CMarketStreamlst& lst,
                                   uint32_t nActvNum = 10);  // 获取当天活跃成交
};

#include "RealTimeDeal/BondMarketStreamV2.h"

#define FOR_EACH_MARKETSTREAM(DAY, it)                                      \
  CMarketStream::Enumerator _mktLst_(&CMarketStream::bondStream(), DAY,     \
                                     false);                                \
  for (CMarketStream::iterator it = _mktLst_.begin(); it != _mktLst_.end(); \
       ++it)
#define FOR_ALL_MARKETSTREAM(DAY, it)                                          \
  CMarketStream::Enumerator _mktLst_(&CMarketStream::bondStream(), DAY, true); \
  for (CMarketStream::iterator it = _mktLst_.begin(); it != _mktLst_.end();    \
       ++it)
#define FOR_EACH_MARKETSTREAM_EX(MS, DAY, it)                               \
  CMarketStream::Enumerator _mktLst_(MS, DAY);                              \
  for (CMarketStream::iterator it = _mktLst_.begin(); it != _mktLst_.end(); \
       ++it)
